/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.trace.trackutils;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.os.StatFs;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.View;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

/**
 * Class containing some static utility methods.
 */
public class Utils {
	private Context context;
	private static boolean flag = false;
	private static File file;

	/**
	 * 检查sd卡是否存在
	 *
	 * @return True if external storage is removable (like an SD card), false
	 *         otherwise.
	 */
	public static boolean isExternalStorageRemovable() {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { // 9
		 	return Environment.isExternalStorageRemovable();
		}
		return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
	}

	/**
	 * 获取/Android/data/ 包名/cache/"
	 *
	 */
	public static File tils(Context context) {
		final String cacheDir = "/Android/data/" + context.getPackageName()
				+ "/cache/";
		return new File(Environment.getExternalStorageDirectory().getPath()
				+ cacheDir);
	}


	/**
	 * 获取手机内存卡中的data目录
	 * @return
	 */
	public static String getCacheDirectory() {
		String path = Environment.getExternalStorageDirectory()
				.getAbsolutePath();

		return path + "/Android/data";
	}
	/**
	 * 获取mnt/Android/data/com.……
	 * @param context
	 * @return
	 */
	public static String getApplicationCacheDirectory(Context context) {
		return getCacheDirectory() + "/" + getApplicationPakageName(context);
	}
	/**
	 * 获取手机内存中的data/data/com.……
	 * @param context
	 * @return
	 */
	public static String getApplicationDataDirectory(Context context) {
		String path = Environment.getDataDirectory().getAbsolutePath();

		return path + "/data/" + getApplicationPakageName(context);
	}
	/**
	 * 获取包名
	 * @param context
	 * @return
	 */
	public static String getApplicationPakageName(Context context) {
		try {
			PackageInfo pkg = context.getPackageManager().getPackageInfo(
					context.getApplicationContext().getPackageName(), 0);
			String pkgName = pkg.packageName;

			return pkgName;
		} catch (PackageManager.NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 检查一个给定的路径可用多少可用空间。
	 *
	 * @param path
	 *            The path to check
	 * @return The space available in bytes
	 */
	public static long getUsableSpace(File path) {
		final StatFs stats = new StatFs(path.getPath());
		return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
	}

	/**
	 * 获得该设备的内存类 (approx. per-app memory limit)
	 *
	 * @param context
	 * @return
	 */
	public static int getMemoryClass(Context context) {
		return ((ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
	}

	/**
	 * 获取当前时间
	 *
	 * @return time
	 */
	public static String getCurrentTime() {
		Date curDate = new Date(System.currentTimeMillis());
		return SimpleDateFormat.getDateInstance().format(curDate);
	}

	/**
	 * 获得今天、明天、后天
	 */
	public static String getFetrueTime(long newTime) {
		String time = "";
		Calendar tempDate = Calendar.getInstance();
		tempDate.set(Calendar.HOUR_OF_DAY, 0);
		tempDate.set(Calendar.SECOND, 0);
		tempDate.set(Calendar.MINUTE, 0);
		long intervalMilli = tempDate.getTimeInMillis()/1000 - newTime/1000;
		int xcts = (int) (intervalMilli / (24 * 60 * 60));
		switch (xcts) {
			case 0:
				time = "今天";
				break;
			case 1:
				time = "昨天";
				break;
			case 2:
				time = "前天";
				break;
			default:
				time = "";
				break;
		}
		return time;
	}

	public static String diffTime(String strDate, String pattern){
		String ret = "";
		try{
			Date now = new Date();

			SimpleDateFormat sdf = new SimpleDateFormat(pattern);
			SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm");
//			Date tmp = sdf.historyPointResult(strDate);
			Date tmp = new Date(Long.parseLong(strDate));

			if(tmp.after(now)){
				return "";
			}
			long s = (now.getTime() - tmp.getTime()) / 1000;
			long count = 0;
//			if((count = s / (3600 * 24 * 365)) > 0){
//				ret = count + "年前";
//			}else if((count = s / (3600 * 24 * 30)) > 0){
//				ret = count + "月前";
//			}else

			if((count = s / 3600 * 24) > 0){
//				ret = count + "天前";
				ret = sdf.format(tmp);
			}else{
				ret = sdf2.format(tmp);
			}
//			else if((count = s / 3600) > 0){
//				ret = count + "小时前";
//			}else if((count = s / 60) > 0){
//				ret = count + "分钟前";
//			}else{
//				ret = "刚刚";
//			}
		}catch (Exception e) {
			log.e(e.toString());
		}

		return ret;
	}

	/**
	 * 计算过期时间
	 *
	 * @return
	 */
	public static String getExpireTime(Long endTime, Long lcc_time) {
		String result;
		int minute = 1000 * 60;
		int hour = minute * 60;
		int day = hour * 24;
//		long now = new Date().getTime();
		if(lcc_time==0){
			return "";
		}
		long diffValue = lcc_time - endTime;
//		if (diffValue < 0) {
//			// 若日期不符则弹出窗口告之
//			long diffValue2 = lcc_time - now;
//			long day2 = diffValue2 / day;
//			long hour2 = (diffValue2 / hour) % 24;
//			long min2 = (diffValue2 / minute) % 60;
//			return day2 + "天" + hour2 + "小时" + min2 + "分钟";
//		}
		long dayC = diffValue / day;
		long hourC = diffValue / hour;
		long minC = diffValue / minute;
		if (dayC > 1) {
			long days = dayC+1;
			result = "已延期" + days + "天";
		} else if (hourC >= 1) {
			result = "已延期" ;
//					+ hourC + "小时";
		} else if (minC >= 1) {
			result = "已延期" ;
//					+ minC + "分钟";
		} else
			result = "";
		return result;
	}

	/**
	 * 过滤字符串中的特殊字符
	 *
	 * @return time
	 */
	public static String stringFilter(String str, String filter) {
		String filterStr = null;
		Matcher m;
		try {
			Pattern p = Pattern.compile(filter);
			m = p.matcher(str);
			filterStr = m.replaceAll("");
		} catch (PatternSyntaxException e) {

		}
		return filterStr;
	}

	/**
	 * 获取当前IMEI 设备号
	 *
	 * @return boolean
	 */
	public static String getDeviceId(Context context) {
		TelephonyManager tm = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		return tm.getDeviceId();
	}

	/**
	 * 获取当前网卡MAC地址
	 *
	 * @return boolean
	 */
	public static String getLocalMacAddress(Context context) {
		WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		WifiInfo info = wifi.getConnectionInfo();
		return info.getMacAddress();
	}

	/**
	 * 获得网络物理地址
	 * @return
	 */
	public static String getLocalMacAddress() {
		String Mac=null;
		try{

			String path="sys/class/net/wlan0/address";
			if((new File(path)).exists())
			{
				FileInputStream fis = new FileInputStream(path);
				byte[] buffer = new byte[8192];
				int byteCount = fis.read(buffer);
				if(byteCount>0)
				{
					Mac = new String(buffer, 0, byteCount, "utf-8");
				}
			}
			if(Mac==null||Mac.length()==0)
			{
				path="sys/class/net/eth0/address";
				FileInputStream fis_name = new FileInputStream(path);
				byte[] buffer_name = new byte[8192];
				int byteCount_name = fis_name.read(buffer_name);
				if(byteCount_name>0)
				{
					Mac = new String(buffer_name, 0, byteCount_name, "utf-8");
				}
			}

			if(Mac.length()==0||Mac==null){
				return "";
			}
		}catch(Exception io){

		}
		return Mac.trim();
	}

	/**
	 * 获取手机ip地址
	 *
	 * @return
	 */
	public static String getPhoneIp() {
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
						// if (!inetAddress.isLoopbackAddress() && inetAddress
						// instanceof Inet6Address) {
						return inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (Exception e) {
		}
		return "";
	}

	/**
	 * 获取设备版本
	 * @return
	 */
	public static String getDeviceVersion()
	{
		return Build.VERSION.RELEASE;
	}

/**
 　　* 获取版本号
 　　* @return 当前应用的版本号
 　　*/
	public static String getVersion(Context context) {
		try {
			PackageManager manager = context.getPackageManager();
			PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
			String version = info.versionName;
			return version;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 　　* 获取版本号
	 　　* @return 当前应用的版本号
	 　　*/
	public static int getVersionCode(Context context) {
		try {
			PackageManager manager = context.getPackageManager();
			PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
			int versionCode = info.versionCode;
			return versionCode;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	public static int getScreenWidth(Context _context) {
		DisplayMetrics mDisplayMetrics = new DisplayMetrics();
		((Activity) _context).getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
		int width = mDisplayMetrics.widthPixels;
		return width;
	}

	public static int getScreenHeight(Activity activity) {
		DisplayMetrics mDisplayMetrics = new DisplayMetrics();
		activity.getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
		int height = mDisplayMetrics.heightPixels;
		return height;
	}

	/**
	 * 文件缓存写入
	 * @param datas
	 * @param context
	 * @param uri
	 */
	public static void writeObject(Object datas, Context context, String uri) {
		File dir = new File(getApplicationDataDirectory(context) + "/cache");
		if (!dir.exists()) {
			dir.mkdirs();
		}
		File file = new File(getApplicationDataDirectory(context) + "/cache/"+uri+".txt");
		if(file.exists()){
			file.delete();
		}
		try {
			FileOutputStream outStream = new FileOutputStream(
					getApplicationDataDirectory(context) + "/cache/"+uri+".txt");
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(
					outStream);

			objectOutputStream.writeObject(datas);
			outStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 写入文件
	 * @param path
	 * @param key
     * @param datas
     */
	public static void writeObject(String path,String key,Object datas){
		File dir = new File(path);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		String filePath = path + "/" + key;
		File file = new File(filePath);
		if(file.exists()){
			file.delete();
		}
		try {
			FileOutputStream outStream = new FileOutputStream(filePath);
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(
					outStream);
			objectOutputStream.writeObject(datas);
			outStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 文件缓存读取
	 * @param context
	 * @param uri
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	public static <T> T readObject(Context context, String uri, Class<T> clazz) {
		FileInputStream freader;
		T datas = null;
		try {
			datas = clazz.newInstance();
			freader = new FileInputStream(
					getApplicationDataDirectory(context) + "/cache/"+uri+".txt");
			ObjectInputStream objectInputStream = new ObjectInputStream(freader);
			datas = (T) objectInputStream.readObject();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return datas;
	}

	/**
	 * 读取文件
	 * @param path
	 * @param key
	 * @param clazz
	 * @param <T>
     * @return
     */
	public static <T> T readObject(String path,String key,Class<T> clazz){
		T datas = null;
		try{
			FileInputStream freader;
			String filePath = path + "/" + key;
			File file = new File(filePath);
			if(file.exists()){
				datas = clazz.newInstance();
				freader = new FileInputStream(filePath);
				ObjectInputStream objectInputStream = new ObjectInputStream(freader);
				datas = (T) objectInputStream.readObject();
			}
		}catch (Exception e){
			e.getStackTrace();
		}
		return datas;
	}



	/**
	 * 定义分割常量 （#在集合中的含义是每个元素的分割，|主要用于map类型的集合用于key与value中的分割）
	 */
	private static final String SEP1 = "#";
	private static final String SEP2 = "|";

	/**
	 * List转换String
	 *
	 * @param list
	 *            :需要转换的List
	 * @return String转换后的字符串
	 */
	public static String ListToString(List<?> list) {
		StringBuffer sb = new StringBuffer();
		if (list != null && list.size() > 0) {
			for (int i = 0; i < list.size(); i++) {
				if (list.get(i) == null || list.get(i) == "") {
					continue;
				}
				// 如果值是list类型则调用自己
				if (list.get(i) instanceof List) {
					sb.append(ListToString((List<?>) list.get(i)));
					sb.append(SEP1);
				} else if (list.get(i) instanceof Map) {
					sb.append(MapToString((Map<?, ?>) list.get(i)));
					sb.append(SEP1);
				} else {
					sb.append(list.get(i));
					sb.append(SEP1);
				}
			}
		}
		return "L" + sb.toString();
	}

	/**
	 * Map转换String
	 *
	 * @param map
	 *            :需要转换的Map
	 * @return String转换后的字符串
	 */
	public static String MapToString(Map<?, ?> map) {
		StringBuffer sb = new StringBuffer();
		// 遍历map
		for (Object obj : map.keySet()) {
			if (obj == null) {
				continue;
			}
			Object key = obj;
			Object value = map.get(key);
			if (value instanceof List<?>) {
				sb.append(key.toString() + SEP1 + ListToString((List<?>) value));
				sb.append(SEP2);
			} else if (value instanceof Map<?, ?>) {
				sb.append(key.toString() + SEP1
						+ MapToString((Map<?, ?>) value));
				sb.append(SEP2);
			} else {
				if(value == null){
					value = "";
				}
				sb.append(key.toString() + SEP1 + value.toString());
				sb.append(SEP2);
			}
		}
		return "M" + sb.toString();
	}

	/**
	 * String转换Map
	 *
	 * @param mapText
	 *            :需要转换的字符串
	 *            :字符串中的分隔符每一个key与value中的分割
	 *            :字符串中每个元素的分割
	 * @return Map<?,?>
	 */
	public static Map<String, Object> StringToMap(String mapText) {

		if (mapText == null || mapText.equals("")) {
			return null;
		}
		mapText = mapText.substring(1);

//        mapText = EspUtils.DecodeBase64(mapText);  

		Map<String, Object> map = new HashMap<String, Object>();
		String[] text = mapText.split("\\" + SEP2); // 转换为数组
		for (String str : text) {
			String[] keyText = str.split(SEP1); // 转换key与value的数组
			if (keyText.length < 1) {
				continue;
			}
			String key = keyText[0]; // key
			String value = keyText[1]; // value
			if (value.charAt(0) == 'M') {
				Map<?, ?> map1 = StringToMap(value);
				map.put(key, map1);
			} else if (value.charAt(0) == 'L') {
				List<?> list = StringToList(value);
				map.put(key, list);
			} else {
				map.put(key, value);
			}
		}
		return map;
	}

	/**
	 * 对象转字节
	 * @param obj
	 * @return
	 */
	public static byte[] objectToByte(Object obj) {
		byte[] bytes = null;
		try {
			// object to bytearray
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
			objectOutputStream.writeObject(obj);
			bytes = byteArrayOutputStream.toByteArray();
			byteArrayOutputStream.close();
			objectOutputStream.close();
		} catch (Exception e) {
			System.out.println("translation" + e.getMessage());
			e.printStackTrace();
		}
		return bytes;
	}

	/**
	 * 字节转对象
	 * @param bytes
	 * @return
	 */
	public static Object byteToObject(byte[] bytes) {
		Object obj = null;
		try {
			// bytearray to object
			ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
			ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);

			obj = objectInputStream.readObject();
			byteArrayInputStream.close();
			objectInputStream.close();
		} catch (Exception e) {
			System.out.println("translation" + e.getMessage());
			e.printStackTrace();
		}
		return obj;
	}
	/**
	 * String转换List
	 *
	 * @param listText
	 *            :需要转换的文本
	 * @return List<?>
	 */
	public static List<Object> StringToList(String listText) {
		if (listText == null || listText.equals("")) {
			return null;
		}
//		listText = listText.substring(1);

//        listText = EspUtils.DecodeBase64(listText);  

		List<Object> list = new ArrayList<Object>();
		String[] text = listText.split(SEP1);
		for (String str : text) {
			if (str.charAt(0) == 'M') {
				Map<?, ?> map = StringToMap(str);
				list.add(map);
			} else if (str.charAt(0) == 'L') {
				List<?> lists = StringToList(str);
				list.add(lists);
			} else {
				list.add(str);
			}
		}
		return list;
	}

	/**
	 *  根据路径删除指定的目录或文件，无论存在与否
	 *@param sPath  要删除的目录或文件
	 *@return 删除成功返回 true，否则返回 false。
	 */
	public static boolean DeleteFolder(String sPath) {
		flag = false;
		file = new File(sPath);
		// 判断目录或文件是否存在
		if (!file.exists()) {  // 不存在返回 false
			return flag;
		} else {
			// 判断是否为文件
			if (file.isFile()) {  // 为文件时调用删除文件方法
				return deleteFile(sPath);
			} else {  // 为目录时调用删除目录方法
				return deleteDirectory(sPath);
			}
		}
	}

	/**
	 * 删除单个文件
	 * @param   sPath    被删除文件的文件名
	 * @return 单个文件删除成功返回true，否则返回false
	 */
	public static boolean deleteFile(String sPath) {
		flag = false;
		file = new File(sPath);
		// 路径为文件且不为空则进行删除
		if (file.isFile() && file.exists()) {
			log.i(file.getName()+"已删除");
			file.delete();
			flag = true;
		}
		return flag;
	}

	/**
	 * 删除目录（文件夹）以及目录下的文件
	 * @param   sPath 被删除目录的文件路径
	 * @return  目录删除成功返回true，否则返回false
	 */
	public static boolean deleteDirectory(String sPath) {
		//如果sPath不以文件分隔符结尾，自动添加文件分隔符
		if (!sPath.endsWith(File.separator)) {
			sPath = sPath + File.separator;
		}
		File dirFile = new File(sPath);
		//如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			return false;
		}
		flag = true;
		//删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			//删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag) break;
			} //删除子目录
			else {
				log.i("目录"+files[i].getAbsolutePath()+"已删除");
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag) break;
			}
		}
		if (!flag) return false;
		//删除当前目录
		return dirFile.delete();
	}

	/**
	 * 解压缩功能.
	 * 将zipFile文件解压到folderPath目录下.
	 * @throws Exception
	 */
	public static void upZipFile(File zipFile, String folderPath)throws IOException {
		//public static void upZipFile() throws Exception{
		ZipFile zfile=new ZipFile(zipFile);
		Enumeration zList=zfile.entries();
		ZipEntry ze=null;
		byte[] buf=new byte[1024];
		while(zList.hasMoreElements()){
			ze=(ZipEntry)zList.nextElement();
			if(ze.isDirectory()){
				String dirstr = folderPath + ze.getName();
				//dirstr.trim();
				dirstr = new String(dirstr.getBytes("8859_1"), "GB2312");
				File f=new File(dirstr);
				f.mkdir();
				continue;
			}
			OutputStream os=new BufferedOutputStream(new FileOutputStream(getRealFileName(folderPath, ze.getName())));
			InputStream is=new BufferedInputStream(zfile.getInputStream(ze));
			int readLen=0;
			while ((readLen=is.read(buf, 0, 1024))!=-1) {
				os.write(buf, 0, readLen);
			}
			is.close();
			os.close();
		}
		zfile.close();
	}

	/**
	 * 给定根目录，返回一个相对路径所对应的实际文件名.
	 * @param baseDir 指定根目录
	 * @param absFileName 相对路径名，来自于ZipEntry中的name
	 * @return java.io.File 实际的文件
	 */
	public static File getRealFileName(String baseDir, String absFileName){
		String[] dirs=absFileName.split("/");
		File ret=new File(baseDir);
		String substr = null;
		if(dirs.length>1){
			for (int i = 0; i < dirs.length-1;i++) {
				substr = dirs[i];
				try {
					//substr.trim();
					substr = new String(substr.getBytes("8859_1"), "GB2312");

				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				ret=new File(ret, substr);

			}
			if(!ret.exists())
				ret.mkdirs();
			substr = dirs[dirs.length-1];
			try {
				//substr.trim();
				substr = new String(substr.getBytes("8859_1"), "GB2312");
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			ret=new File(ret, substr);
			return ret;
		}
		return ret;
	}
//
//	/**
//	 * 复制文件夹或文件夹
//	 */
//	public static void CopyDirectoryOrFile(String url1, String url2)
//			throws IOException {
//		// 创建目标文件夹
//		File desDir = new File(url2);
//		if (!desDir.exists()) {
//			desDir.mkdirs();
//		}
//		// 获取源文件夹当前下的文件或目录
//		File[] file = (new File(url1)).listFiles();
//		for (int PushModule = 0; PushModule < file.length; PushModule++) {
//			if (file[PushModule].isFile()) {
//				// 复制文件
//				copyFile(file[PushModule], new File(url2 + file[PushModule].getName()));
//			}
//			if (file[PushModule].isDirectory()) {
//				// 复制目录
//				String sourceDir = url1 + File.separator + file[PushModule].getName();
//				String targetDir = url2 + File.separator + file[PushModule].getName();
//				copyDirectiory(sourceDir, targetDir);
//			}
//		}
//	}
//
//	// 复制文件
//	public static void copyFile(File sourceFile, File targetFile) throws IOException {
//		// 新建文件输入流并对它进行缓冲
//		FileInputStream input = new FileInputStream(sourceFile);
//		BufferedInputStream inBuff = new BufferedInputStream(input);
//
//		// 新建文件输出流并对它进行缓冲
//		FileOutputStream output = new FileOutputStream(targetFile);
//		BufferedOutputStream outBuff = new BufferedOutputStream(output);
//
//		// 缓冲数组
//		byte[] b = new byte[1024 * 5];
//		int len;
//		while ((len = inBuff.read(b)) != -1) {
//			outBuff.write(b, 0, len);
//		}
//		// 刷新此缓冲的输出流
//		outBuff.flush();
//
//		// 关闭流
//		inBuff.close();
//		outBuff.close();
//		output.close();
//		input.close();
//	}
//
//	// 复制文件夹
//	public static void copyDirectiory(String sourceDir, String targetDir)
//			throws IOException {
//		// 新建目标目录
//		(new File(targetDir)).mkdirs();
//		// 获取源文件夹当前下的文件或目录
//		File[] file = (new File(sourceDir)).listFiles();
//		for (int PushModule = 0; PushModule < file.length; PushModule++) {
//			if (file[PushModule].isFile()) {
//				// 源文件
//				File sourceFile = file[PushModule];
//				// 目标文件
//				File targetFile = new File(
//						new File(targetDir).getAbsolutePath() + File.separator
//								+ file[PushModule].getName());
//				copyFile(sourceFile, targetFile);
//			}
//			if (file[PushModule].isDirectory()) {
//				// 准备复制的源文件夹
//				String dir1 = sourceDir + "/" + file[PushModule].getName();
//				// 准备复制的目标文件夹
//				String dir2 = targetDir + "/" + file[PushModule].getName();
//				copyDirectiory(dir1, dir2);
//			}
//		}
//	}


	public static void copyFileOrDir(String path, Context context) {
		AssetManager assetManager = context.getAssets();
		String assets[] = null;
		try {
			assets = assetManager.list(path);
			if (assets.length == 0) {
				copyFile(path,context);
			} else {
				String fullPath = getApplicationDataDirectory(context) + "/" + path;
				File dir = new File(fullPath);
				if (!dir.exists())
					dir.mkdir();
				for (int i = 0; i < assets.length; ++i) {
					copyFileOrDir(path + "/" + assets[i],context);
				}
			}
		} catch (IOException ex) {

		}
	}

	private static void copyFile(String filename, Context context) {
		AssetManager assetManager = context.getAssets();

		InputStream in = null;
		OutputStream out = null;
		try {
			in = assetManager.open(filename);
			String newFileName = getApplicationDataDirectory(context) + "/" + filename;
			out = new FileOutputStream(newFileName);

			byte[] buffer = new byte[1024];
			int read;
			while ((read = in.read(buffer)) != -1) {
				out.write(buffer, 0, read);
			}
			in.close();
			in = null;
			out.flush();
			out.close();
			out = null;
		} catch (Exception e) {

		}

	}


	public static class ViewHolder {
		public static <T extends View> T get(View view, int id) {
			SparseArray viewHolder = (SparseArray) view.getTag();
			if (viewHolder == null) {
				viewHolder = new SparseArray();
				view.setTag(viewHolder);
			}
			View childView = (View) viewHolder.get(id);
			if (childView == null) {
				childView = view.findViewById(id);
				viewHolder.put(id, childView);
			}
			return (T) childView;
		}
	}

	public static class Base64 {
		private static final byte EQUALS_SIGN = 61;
		private static final String PREFERRED_ENCODING = "US-ASCII";
		private static final byte[] _STANDARD_ALPHABET = { 65, 66, 67, 68, 69,
				70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
				86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105,
				106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
				118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56,
				57, 43, 47 };

		private static byte[] encode3to4(byte[] source, int srcOffset,
										 int numSigBytes, byte[] destination, int destOffset) {
			byte[] ALPHABET = _STANDARD_ALPHABET;

			int inBuff = ((numSigBytes > 0) ? source[srcOffset] << 24 >>> 8 : 0)
					| ((numSigBytes > 1) ? source[(srcOffset + 1)] << 24 >>> 16
					: 0)
					| ((numSigBytes > 2) ? source[(srcOffset + 2)] << 24 >>> 24
					: 0);

			switch (numSigBytes) {
				case 3:
					destination[destOffset] = ALPHABET[(inBuff >>> 18)];
					destination[(destOffset + 1)] = ALPHABET[(inBuff >>> 12 & 0x3F)];
					destination[(destOffset + 2)] = ALPHABET[(inBuff >>> 6 & 0x3F)];
					destination[(destOffset + 3)] = ALPHABET[(inBuff & 0x3F)];
					return destination;
				case 2:
					destination[destOffset] = ALPHABET[(inBuff >>> 18)];
					destination[(destOffset + 1)] = ALPHABET[(inBuff >>> 12 & 0x3F)];
					destination[(destOffset + 2)] = ALPHABET[(inBuff >>> 6 & 0x3F)];
					destination[(destOffset + 3)] = 61;
					return destination;
				case 1:
					destination[destOffset] = ALPHABET[(inBuff >>> 18)];
					destination[(destOffset + 1)] = ALPHABET[(inBuff >>> 12 & 0x3F)];
					destination[(destOffset + 2)] = 61;
					destination[(destOffset + 3)] = 61;
					return destination;
			}

			return destination;
		}

		public static String encode(String string) {
			byte[] bytes;
			try {
				bytes = string.getBytes("US-ASCII");
			} catch (UnsupportedEncodingException e) {
				bytes = string.getBytes();
			}
			return encodeBytes(bytes);
		}

		public static String encodeBytes(byte[] source) {
			return encodeBytes(source, 0, source.length);
		}

		public static String encodeBytes(byte[] source, int off, int len) {
			byte[] encoded = encodeBytesToBytes(source, off, len);
			try {
				return new String(encoded, "US-ASCII");
			} catch (UnsupportedEncodingException uue) {
			}
			return new String(encoded);
		}

		public static byte[] encodeBytesToBytes(byte[] source, int off, int len) {
			if (source == null) {
				throw new NullPointerException("Cannot serialize a null array.");
			}
			if (off < 0) {
				throw new IllegalArgumentException(
						"Cannot have negative offset: " + off);
			}
			if (len < 0) {
				throw new IllegalArgumentException(
						"Cannot have length offset: " + len);
			}
			if (off + len > source.length) {
				throw new IllegalArgumentException(
						String.format(
								"Cannot have offset of %d and length of %d with array of length %d",
								new Object[] { Integer.valueOf(off),
										Integer.valueOf(len),
										Integer.valueOf(source.length) }));
			}

			int encLen = len / 3 * 4 + ((len % 3 > 0) ? 4 : 0);

			byte[] outBuff = new byte[encLen];

			int d = 0;
			int e = 0;
			int len2 = len - 2;
			for (; d < len2; e += 4) {
				encode3to4(source, d + off, 3, outBuff, e);

				d += 3;
			}

			if (d < len) {
				encode3to4(source, d + off, len - d, outBuff, e);
				e += 4;
			}

			if (e <= outBuff.length - 1) {
				byte[] finalOut = new byte[e];
				System.arraycopy(outBuff, 0, finalOut, 0, e);
				return finalOut;
			}
			return outBuff;
		}
	}




	/**
	 * 判断当前网络是否可用
	 *
	 * @return boolean
	 */
	public static boolean isNetworkAvailable(Context context) {
		try {

			ConnectivityManager cm = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);

			NetworkInfo info = cm.getActiveNetworkInfo();
			return (info != null && info.isConnected());
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 判断网络是否连接
	 * @param context
	 * @return
	 */
	public static boolean isNetworkConnected(Context context) {
		if (context != null) {
			ConnectivityManager mConnectivityManager = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
			if (mNetworkInfo != null) {
				return mNetworkInfo.isAvailable();
			}
		}
		return false;
	}

	/**
	 * 判断当前的wifi 是否可用
	 * @param context
	 * @return
	 */
	public static boolean isWifiConnected(Context context) {
		if (context != null) {
			ConnectivityManager mConnectivityManager = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo mWiFiNetworkInfo = mConnectivityManager
					.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
			if (mWiFiNetworkInfo != null) {
				return mWiFiNetworkInfo.isAvailable();
			}
		}
		return false;
	}

	/**
	 * 判断当前的手机网络是否可用
	 * @param context
	 * @return
	 */
	public static boolean isMobileConnected(Context context) {
		if (context != null) {
			ConnectivityManager mConnectivityManager = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo mMobileNetworkInfo = mConnectivityManager
					.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
			if (mMobileNetworkInfo != null) {
				return mMobileNetworkInfo.isAvailable();
			}
		}
		return false;
	}

	public static boolean isValid(String string) {
		return ((string == null) || (TextUtils.isEmpty(string.trim())));
	}

	public static boolean isInMainThread() {
		return Looper.myLooper() == Looper.getMainLooper();
	}

	public static  boolean isNotNull(String valid){
		return !(valid.equals("") || valid.length() <= 0);
	}

	public static  boolean isNull(String valid){
		return !(!valid.equals("") && valid.length() >= 0);
	}



	/**
	 * 判断进程是否运行
	 * @return
	 */
	public static boolean isProessRunning(Context context, String proessName) {

		boolean isRunning = false;
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);

		List<ActivityManager.RunningAppProcessInfo> lists = am.getRunningAppProcesses();
		for (ActivityManager.RunningAppProcessInfo info : lists) {
			if (info.processName.equals(proessName)) {
				isRunning = true;
			}
		}

		return isRunning;
	}


	/**
	 * 文件操作辅助类
	 * @author Amethy
	 *
	 */
	public static class FileUtils {

		/**
		 * 将文件内容读取到字符串中
		 * @param filename	文件名
		 * @return	字符串
		 */
		public static String readStringFromFile(String filename) {
			String reads = null;

			FileInputStream fis = null;
			ByteArrayOutputStream baos = null;
			try {
				fis = new FileInputStream(filename);
				if (fis != null) {
					baos = new ByteArrayOutputStream();
					byte[] data = new byte[1024];
					int len = 0;
					while ((len = fis.read(data)) != -1) {
						baos.write(data, 0, len);
					}
					reads = baos.toString();
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if (fis != null) {
						fis.close();
					}
					if (baos != null) {
						baos.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			return reads;
		}

		/**
		 * 将文件内容读取到字节数组中
		 * @param filename 文件名
		 * @return
		 */
		public static byte[] readByteArrayFromFile(String filename) {
			byte[] reads = null;

			FileInputStream fis = null;
			ByteArrayOutputStream baos = null;
			try {
				fis = new FileInputStream(filename);
				if (fis != null) {
					baos = new ByteArrayOutputStream();
					byte[] data = new byte[1024];
					while (fis.read(data) != -1) {
						baos.write(data, 0, data.length);
					}
					reads = baos.toByteArray();
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if (fis != null) {
						fis.close();
					}
					if (baos != null) {
						baos.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			return reads;
		}

		/**
		 * 将Bitmap对象保存到文件
		 * @param bitmap	要保存的Bitmap对象
		 * @param filename	保存的文件路径
		 */
		public static void writeBitmap(Bitmap bitmap, String filename) {
			FileOutputStream fos = null;
			try {
				File file = new File(filename);
				if (file.getParentFile() != null) {
					file.getParentFile().mkdirs();
				}

				if (file.exists()) {
					file.delete();
				}

				file.createNewFile();

				fos = new FileOutputStream(new File(filename));
				if (filename.toLowerCase().endsWith(".jpg")) {
					bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
				} else {
					bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
				}
				fos.flush();
			} catch (Exception e) {
				log.e(e.getMessage());
			} finally {
				if (fos != null) {
					try {
						fos.close();
					} catch (IOException e) {
						log.e(e.getMessage());
					}
				}
			}
		}

		/**
		 * 写入文件
		 * @param data		写入的数据
		 * @param dirName	写入文件所在目录
		 * @param filename	写入的文件名
		 * @param type		写入的文件类型
		 */
		public static void writeToFile(byte[] data, String dirName, String filename, String type) {
			if (filename == null) {
				throw new IllegalArgumentException("filename should not be null");
			}
			FileOutputStream fos = null;

			if (dirName == null) {
				dirName = Environment.getExternalStorageDirectory().getAbsolutePath();
			} else {
				new File(dirName).mkdirs();
			}

			try {
				fos = new FileOutputStream(new File(dirName + "/" +filename + "." + type));
				fos.write(data);
				fos.flush();
			} catch (Exception e) {
			} finally {
				try {
					if (fos != null) {
						fos.close();
					}
				} catch (IOException e) {
				}
			}
		}

		/**
		 * 从输入流中获取数据并写入文件
		 * @param is		输入流
		 * @param filename	写入的文件路径
		 */
		public static void writeToFile(InputStream is, String filename) {
			if (filename == null) {
				throw new IllegalArgumentException("filename should not be null");
			}

			FileOutputStream fos = null;
			File file = new File(filename);
			file.getParentFile().mkdirs();

			try {
				file.createNewFile();
				fos = new FileOutputStream(file);

				byte[] buffer = new byte[40280];
				int len = 0;
				while ((len = is.read(buffer)) != -1) {
					fos.write(buffer, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fos.flush();
					fos.close();
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		/**
		 * 写入文件
		 * @param data		写入的数据源
		 * @param offset	数据源开始写入位置
		 * @param len		写入的长度
		 * @param filename	保存的文件名
		 */
		public static void writeToFile(byte[] data, int offset, int len, String filename) {
			if (filename == null) {
				throw new IllegalArgumentException("filename should not be null");
			}
			FileOutputStream fos = null;
			File file = new File(filename);
			file.getParentFile().mkdirs();
			try {
				file.createNewFile();
				fos = new FileOutputStream(file);
				fos.write(data, offset, len);
				fos.flush();
			} catch (Exception e) {
				log.e(e.getMessage());
			} finally {
				try {
					if (fos != null) {
						fos.close();
					}
				} catch (IOException e) {
					log.e(e.getMessage());
				}
			}
		}

		/**
		 * 写入文件
		 * @param data		要写入的数据
		 * @param filename	要写入的文件路径
		 */
		public static void writeToFile(byte[] data,/* String dirName,*/ String filename) {
			/*if (filename == null) {
				throw new IllegalArgumentException("filename should not be null");
			}
			FileOutputStream fos = null;
			File file = new File(filename);
			file.getParentFile().mkdirs();
			LogInfo.d("writeFile", "write size: " + data.length, LOGABLE);
			try {
				file.createNewFile();
				fos = new FileOutputStream(file);
				fos.write(data);
				fos.flush();
			} catch (Exception e) {
				LogInfo.e("WriteToFile", e.getMessage());
			} finally {
				try {
					if (fos != null) {
						fos.close();
					}
				} catch (IOException e) {
					LogInfo.e("WriteToFile", e.getMessage());
				}
			}*/
			writeToFile(data, 0, data.length, filename);
		}

		public static void writeToFile(byte[] data, int offset, int len, String dirname, String filename, String type) {
			String file = dirname + "/" + filename + "." + type;
			writeToFile(data, offset, len, file);
		}

		@SuppressWarnings("unused")
		private static String createFolder(String newfolder) {
			try {
				File filePath = new File(newfolder);
				if (!filePath.exists()) {
					filePath.mkdirs();
				}
				return filePath.getAbsolutePath();
			} catch (Exception e) {
				log.e("path "+newfolder+ " does exist");
				return null;
			}
		}

		public static boolean isFileAvailable(File file) {

			return file.exists() && file.canRead();
		}

		public static boolean isFileAvailable(String filename) {

			return isFileAvailable(new File(filename));
		}
	}

	/**
	 *
	 * dp、sp 转换为 px 的工具类
	 * @author Amethy
	 *
	 */
	public static class DensityUtil {
		/**
		 * 将dip或dp值转换为px值，保证尺寸大小不变
		 */
		public static int dip2px(Context context, float dpValue) {
			final float scale = context.getResources().getDisplayMetrics().density;

			return (int) (dpValue * scale + 0.5f);
		}

		/**
		 * 将px值转换为dip或dp值，保证尺寸大小不变
		 */
		public static int px2dip(Context context, float pxValue) {
			final float scale = context.getResources().getDisplayMetrics().density;

			return (int) (pxValue / scale + 0.5f);
		}

		public static int dp2px(Context context, int dp) {
			return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
					context.getResources().getDisplayMetrics());
		}

		/**
		 * 将px值转换为sp值，保证文字大小不变
		 * @param context
		 * @param pxValue
		 * @return
		 */
		public static int px2sp(Context context, float pxValue) {
			final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;

			return (int) (pxValue / fontScale + 0.5f);
		}

		/**
		 * 将sp值转换为px值，保证文字大小不变
		 * @param context
		 * @param spValue
		 * @return
		 */
		public static int sp2px(Context context, float spValue) {
			final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;

			return (int) (spValue * fontScale + 0.5f);
		}
	}
}
